package com.puny.mvc.views
{
	import com.puny.mvc.MvcEvent;
	import com.puny.mvc.controllers.Controller;
	import com.puny.mvc.helpers.DelayHelper;
	import com.puny.testframework.TestCaseWithStage;
	
	import flash.errors.IllegalOperationError;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.geom.Point;
	import flash.utils.Timer;

	public class ViewTest extends TestCaseWithStage
	{
		public function ViewTest(methodName:String=null)
		{
			super(methodName);
		}
		
		public function testExternalFile():void {
			var view:View = new SampleView();
			view.addEventListener(MvcEvent.READY, addAsync(readyHandler, 4000));
			view.addEventListener(MvcEvent.COMPLETED, addAsync(completeHandler, 8002));
			mainStage.addChild(view);
		}
		
		public function testEmbededFile():void {
			//pass the instance of embedded swf class.
			var view:View = new EmbededView();
			view.addEventListener(MvcEvent.READY, addAsync(readyHandler, 4000));
			view.addEventListener(MvcEvent.COMPLETED, addAsync(completeHandler, 4000));
			mainStage.addChild(view);
		}
		
		public function testEmbededFile2():void {
			//pass the cass of the embedded swf.
			var view:View = new Embeded2View();
			view.addEventListener(MvcEvent.READY, addAsync(readyHandler, 4000));
			view.addEventListener(MvcEvent.COMPLETED, addAsync(completeHandler, 4000));
			mainStage.addChild(view);
		}

		private function readyHandler(event:Event):void {
			assertEquals(1,event.currentTarget.numChildren);
		}
		
		private function completeHandler(event:Event):void {
			var children:int = mainStage.numChildren;
			mainStage.removeChild(event.currentTarget as View);
			assertEquals(children-1,mainStage.numChildren);
		}
		
		//Test for open procedure.
		// READY event -> beforeOpen() -> procedureOpen -> OPENED event -> afterOpen.
		public function testOpenProcedure():void {
			var view:OpenView = new OpenView();
			view.addEventListener(MvcEvent.READY, addAsync(openReadyHandler, 40000));
			view.addEventListener(MvcEvent.OPENED, addAsync(openOpenedHandler, 100000));
			view.addEventListener(MvcEvent.COMPLETED, addAsync(openCompletedHandler, 110000));
			mainStage.addChild(view);
		}
		
		private function openReadyHandler(event:Event):void {
			//This should be between READY event and beforeOpen.
			var view:OpenView = event.currentTarget as OpenView;
			assertFalse(view._before);
			assertFalse(view._after);
			assertEquals(100,view._count);	
		}
		
		private function openOpenedHandler(event:Event):void {
			//This should be between OPENED event and afterOpen
			var view:OpenView = event.currentTarget as OpenView;
			assertTrue(view._before);
			assertFalse(view._after);
			assertEquals(0,view._count);
			view.complete();
			view.complete();
		}

		private function openCompletedHandler(event:Event):void {
			//This should be after afterOpen.
			var view:OpenView = event.currentTarget as OpenView;
			assertTrue(view._before);
			assertTrue(view._after);
			assertEquals(0,view._count);	
			mainStage.removeChild(event.currentTarget as View);
		}
		
		public function testCloseProcedure():void {
			var view:CloseView = new CloseView();
			mainStage.addChild(view);
			view.addEventListener(MvcEvent.COMPLETED, closeCompletedHandler);
			DelayHelper.setup(1000, null,view.complete);
		}
		
		private function closeCompletedHandler(event:Event):void {
			var view:CloseView = event.currentTarget as CloseView;
			assertTrue(view._before);
			assertTrue(view._after);
			assertEquals(0,view._count);
			mainStage.removeChild(view);
		}
		
		private var _mainFrameView:MainFrameView;
		public function testMainFrame():void {
			var view:MainFrameView = new MainFrameView();
			_mainFrameView = view;
			//procedureMainFrame never ends until complete is invoked.
			view.addEventListener(MvcEvent.COMPLETED, addAsync(mainFrameHandler, 1500));
			mainStage.addChild(view);
			DelayHelper.setup(1000,null,view.complete);
			DelayHelper.setup(500,null,checkMainFrame);
		}
		
		private function checkMainFrame():void {
			//Still loop should be alive.
			assertFalse(_mainFrameView._after);
			//so restartMainFrame should fail.
			assertFalse(_mainFrameView.restartMainFrame());
		}
		
		private function mainFrameHandler(event:Event):void {
			var view:MainFrameView = event.currentTarget as MainFrameView;
			assertTrue(view._after);
			mainStage.removeChild(event.currentTarget as View);
		}
		
		private var _mainFrameView2:MainFrameView;
		public function testMainFrame2():void {
			_mainFrameView2 = new MainFrameView();
			//procedureMainFrame ends immediately because _loop = true at afterReady.
			_mainFrameView2.addEventListener(MvcEvent.READY, addAsync(mainFrameReadyHandler, 1000));
			_mainFrameView2.addEventListener(MvcEvent.COMPLETED, addAsync(mainFrameHandler, 1500));
			mainStage.addChild(_mainFrameView2);
			DelayHelper.setup(500,null, checkMainFrame2);
			DelayHelper.setup(1000,null,_mainFrameView2.complete);
		}
		
		private function checkMainFrame2():void {
			//Still loop should end.
			assertTrue(_mainFrameView2._after);
			//so restartMainFrame should success.
			assertTrue(_mainFrameView2.restartMainFrame());
		}
		
		private function mainFrameReadyHandler(event:Event):void {
			var view:MainFrameView = event.currentTarget as MainFrameView;
			//stop loop!
			view._loop = false;			
		}
		
		public function testNoAssetsView():void {
			var view:NoAssetsView = new NoAssetsView();
			view.addEventListener(MvcEvent.READY, addAsync(noAssetsReadyHandler,10000));
			view.addEventListener(MvcEvent.OPENED, addAsync(noAssetsOpenedHandler,11000));
			view.addEventListener(MvcEvent.COMPLETED, addAsync(noAssetsCompletedHandler,12000));
			var ctrl:Controller = new Controller();
			ctrl.addChild(view);
			mainStage.addChild(ctrl);
			assertTrue(view._setup);
		}
		
		private function noAssetsReadyHandler(event:Event):void {
			var view:NoAssetsView = event.currentTarget as NoAssetsView;
			assertTrue(view._setup);
			assertFalse(view._afterReady);
			assertFalse(view._afterOpen);
			assertFalse(view._afterMainFrame);
			assertFalse(view._afterClose);
			assertFalse(view._afterChildrenRemoved);
		}

		private function noAssetsOpenedHandler(event:Event):void {
			var view:NoAssetsView = event.currentTarget as NoAssetsView;
			assertTrue(view._setup);
			assertTrue(view._afterReady);
			assertFalse(view._afterOpen);
			assertFalse(view._afterMainFrame);
			assertFalse(view._afterClose);
			assertFalse(view._afterChildrenRemoved);
			DelayHelper.setup(5000,null,view.complete);
		}

		private function noAssetsCompletedHandler(event:Event):void {
			var view:NoAssetsView = event.currentTarget as NoAssetsView;
			assertTrue(view._setup);
			assertTrue(view._afterReady);
			assertTrue(view._afterOpen);
			assertTrue(view._afterMainFrame);
			assertTrue(view._afterClose);
			assertFalse(view._afterChildrenRemoved);
		}
		
		public function testSpriteView():void {
			var ctrl:Controller = new Controller();
			var view:View = new SpriteView("assets/scholastic_choose_chara.swf");
			view.addEventListener(MvcEvent.READY, addAsync(loadedHandler,4000));
			ctrl.addChildAt(view,0);
			mainStage.addChild(ctrl);
			assertEquals(1, ctrl.numChildren);
			assertEquals(0, view.bytesTotal);
		}
		
		private function loadedHandler(event:Event):void {
			var view:View = event.currentTarget as View;
			assertEquals(111898, view.bytesTotal);
			assertEquals(111898, view.bytesLoaded);
			assertEquals(100,view.percentageofLoaded);
			view.addChild(new Controller());
		}
		
		public function testWrongFile():void {
			var view:View;
			view = new CommonView("assets/nonexists.swf");
		}
		
		public function testXML():void {
			var xml:XML = new XML("<test><view url=\"assets/scholastic_choose_chara.swf\"/></test>");
			new CommonView(xml.view[0].@src);
		}
		
		public function testWrongObject():void {
			var view:View;
			try {
				view = new CommonView(new Point());
			} catch (e:Error) {
				assertTrue(e is TypeError);
			}
		}
		
		private var _delayView:View;
		public function testDelay():void {
			_delayView = new SampleView();
			_delayView.addEventListener(MvcEvent.COMPLETED, addAsync(completeHandler, 4000));
			var timer:Timer = new Timer(3000,1);
			timer.addEventListener(TimerEvent.TIMER, delayAddingHandler);
			timer.start();
		}
		
		private function delayAddingHandler(event:Event):void {
			mainStage.addChild(_delayView);
		}
		
		public function testBootTwice():void {
			try {
				new BootTwiceView();
			} catch(e:Error) {
				assertEquals("Error: Can't boot more than once.",e);
			}
		}
	}
}